#!/usr/bin/python
'''
This is a port to Python of
C:\Documents and Settings\All Users\Documents\National Instruments\NI-DAQ\Examples\DAQmx ANSI C\Analog In\Measure Voltage\Cont Acq-Int Clk
using the nidaqmx module.

Continuous reads are acheived by configuring the DAQ and then allowing it
to run independantly. After a specified number of samples have been read
into the DAQ buffer a callback function is called and expected to clear
the buffer.
The callback function is processed in a separate thread.
'''

import sys
sys.path.append('..')

import pylab as pl
import nidaqmx as DAQmx
import time

fullData = [] #DAQ data will be agregated here

# There are two different options for the callback function
# The one used depends on which C callback helper was selected
def EveryNCallback(taskHandle, everyNsamplesEventType, nSamples) :
    '''
    This callback used with EveryNCallPython_cb. This callback is 
    expected to handle any reads necissary to empty the buffer.
    '''
    global fullData
    
    data = DAQmx.ReadAnalogF64(taskHandle,nSamples,10.0, \
            DAQmx.Val_GroupByChannel,nSamples,None)
    fullData += data
    print "Acquired %d points. Total points: %d" % (len(data), len(fullData))
    
    return DAQmx.Success

def ReadDoneCallback(sampsPerChanRead, dataRead) :
    '''
    This callback used with ReadAnalogF64_cb. This callback is optimized
    for analog reads. ReadAnalogF64_cb pre-reads the buffer and passes
    a list of the resutls to this function.
    '''
    global fullData
    fullData += dataRead
    print "Acquired %d points. Total points: %d" % (len(dataRead), len(fullData))
    	
    return 0


def main() :
    nSamples = 1000 #Number of samples to read before calling Python back
    
    h = DAQmx.CreateTask("ContAcq")             #Create a new task
    #Configure to read a voltage
    DAQmx.CreateAIVoltageChan(h,"Dev1/ai1","",\
            DAQmx.Val_Cfg_Default,-10.0,10.0,\
            DAQmx.Val_Volts,None)        
    #Configure a continuous clock
    DAQmx.CfgSampClkTiming(h,"",10000.0,\
            DAQmx.Val_Rising,DAQmx.Val_ContSamps,\
            nSamples)

    if True :
        #Optimized analog read
        DAQmx.RegisterEveryNSamplesEvent(h, DAQmx.Val_Acquired_Into_Buffer,\
                nSamples,0, DAQmx.ReadAnalogF64_cb,ReadDoneCallback)
    else :
        #Generic callback
        DAQmx.RegisterEveryNSamplesEvent(h, DAQmx.Val_Acquired_Into_Buffer,\
                nSamples,0, DAQmx.EveryNCallPython_cb,EveryNCallback)

    #TODO: DAQmxRegisterDoneEvent callbacks are not yet supported
    #CHK(nidaq.DAQmxRegisterDoneEvent(taskHandle,0,DoneCallback_func,None));
    #Raise event when a task stops due to an error or when a finite
    #acquisition task or finite generation task completes execution.
    #No event raised when DAQmx.StopTask is called.

    DAQmx.StartTask(h)      #Begin reading
    
    time.sleep(2.0)         #Idle this thread while reading is performed

    DAQmx.StopTask(h)       #Stop reading
    h = DAQmx.ClearTask(h)  #Clear the task
    
    #Use PyLab to plot the results
    pl.plot( fullData )
    pl.show()
    
if __name__ == "__main__":
    main()
